package com.atgouwu.mall.ware.service.impl;

import com.atgouwu.mall.common.exception.NoStockException;
import com.atgouwu.mall.common.mq.StockDetailTo;
import com.atgouwu.mall.common.mq.StockLockedTo;
import com.atgouwu.mall.ware.entity.WareOrderTaskDetailEntity;
import com.atgouwu.mall.ware.entity.WareOrderTaskEntity;
import com.atgouwu.mall.ware.service.WareOrderTaskDetailService;
import com.atgouwu.mall.ware.service.WareOrderTaskService;
import com.atgouwu.mall.ware.vo.OrderItemVo;
import com.atgouwu.mall.ware.vo.SkuHasStockVo;
import com.atgouwu.mall.ware.vo.WareSkuLockVo;
import lombok.Data;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atgouwu.mall.common.utils.PageUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.atgouwu.mall.ware.dao.WareSkuDao;
import com.atgouwu.mall.ware.entity.WareSkuEntity;
import com.atgouwu.mall.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private WareOrderTaskService wareOrderTaskService;
    @Autowired
    private WareSkuDao wareSkuDao;
    @Autowired
    private WareOrderTaskDetailService wareOrderTaskDetailService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<WareSkuEntity> page = this.page(
                new Page<>(Long.valueOf(String.valueOf(params.get("page"))), Long.valueOf(String.valueOf(params.get("size")))),
                new QueryWrapper<WareSkuEntity>()
        );
        return new PageUtils(page.getRecords(), (int) page.getTotal(), (int) page.getSize(), (int) page.getCurrent());
    }

    //查询sku是否有库存
    @Override
    public List<SkuHasStockVo> getSkuHasStock(List<Long> skuIds) {
        List<SkuHasStockVo> skuHasStockVos = skuIds.stream().map(item -> {
            Long count = baseMapper.getSkuStock(item);
            SkuHasStockVo skuHasStockVo = new SkuHasStockVo();
            skuHasStockVo.setSkuId(item);
            skuHasStockVo.setHasStock(count == null ? false : count > 0);
            return skuHasStockVo;
        }).collect(Collectors.toList());
        return skuHasStockVos;
    }

    //锁库存
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean orderLockStock(WareSkuLockVo vo) {
        WareOrderTaskEntity wareOrderTaskEntity = new WareOrderTaskEntity();
        wareOrderTaskEntity.setOrderSn(vo.getOrderSn());
        wareOrderTaskEntity.setCreateTime(new Date());
        wareOrderTaskService.save(wareOrderTaskEntity); //保存库存工作单
        List<OrderItemVo> locks = vo.getLocks();
        List<SkuWareHasStock> collect = locks.stream().map((item) -> { //按下单收货地址找到就近仓库锁定
            SkuWareHasStock stock = new SkuWareHasStock();
            Long skuId = item.getSkuId();
            stock.setSkuId(skuId);
            stock.setNum(item.getCount());
            List<Long> wareIdList = wareSkuDao.listWareIdHasSkuStock(skuId); //获取商品有库存的仓库
            stock.setWareId(wareIdList);
            return stock;
        }).collect(Collectors.toList());
        for (SkuWareHasStock hasStock : collect) {
            boolean skuStocked = false;
            Long skuId = hasStock.getSkuId();
            List<Long> wareIds = hasStock.getWareId();
            if (CollectionUtils.isEmpty(wareIds)) { //没有仓库有库存
                throw new NoStockException(skuId);
            }
            for (Long wareId : wareIds) {
                Long count = wareSkuDao.lockSkuStock(skuId, wareId, hasStock.getNum()); //锁库存(成功返回1,失败返回0)
                if (count == 1) {
                    skuStocked = true;
                    WareOrderTaskDetailEntity taskDetailEntity = WareOrderTaskDetailEntity.builder().skuId(skuId).skuName("").skuNum(hasStock.getNum()).taskId(wareOrderTaskEntity.getId()).wareId(wareId).lockStatus(1).build();
                    wareOrderTaskDetailService.save(taskDetailEntity); //保存库存工作单详细
                    StockLockedTo lockedTo = new StockLockedTo();
                    lockedTo.setId(wareOrderTaskEntity.getId());
                    StockDetailTo detailTo = new StockDetailTo();
                    BeanUtils.copyProperties(taskDetailEntity, detailTo);
                    lockedTo.setDetailTo(detailTo);
                    //rabbitTemplate.convertAndSend("stock-event-exchange", "stock.locked", lockedTo); //告诉MQ库存锁成功
                    break;
                } //当前仓库锁失败,循环重试下一个仓库
            }
            if (skuStocked == false) { //所有仓库都没锁住
                throw new NoStockException(skuId);
            }
        }
        return true; //锁成功
    }

    @Data
    class SkuWareHasStock {
        private Long skuId;
        private Integer num;
        private List<Long> wareId;
    }

}